/**
 * @file socket_server.h
 * @author fwy (2643660853@qq.com)
 * @brief 服务器套接字类
 * @version 0.1
 * @date 2025-08-17
 *
 * @copyright Copyright (c) 2025
 *
 */

#pragma once

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <thread>
#include <functional>
#include <mutex>
#include <atomic>
#include <arpa/inet.h>
#include <unistd.h>

class SocketServer
{
public:
    using MessageCallback = std::function<void(const std::string &client_id, const std::string &message)>;
    using ClientConnectCallback = std::function<void(const std::string &client_id)>;
    using ClientDisconnectCallback = std::function<void(const std::string &client_id)>;

    SocketServer();
    ~SocketServer();

    // 初始化并开始监听
    bool start(int port);

    // 向特定客户端发送消息
    bool sendMessage(const std::string &message, const std::string &client_id);

    // 广播消息给所有客户端
    bool broadcastMessage(const std::string &message);

    // 设置接收消息的回调
    void setMessageCallback(const MessageCallback &callback) { message_callback_ = callback; }

    // 设置客户端连接的回调
    void setClientConnectCallback(const ClientConnectCallback &callback) { client_connect_callback_ = callback; }

    // 设置客户端断开连接的回调
    void setClientDisconnectCallback(const ClientDisconnectCallback &callback) { client_disconnect_callback_ = callback; }

    // 获取所有客户端ID
    std::vector<std::string> getClientIds();

    // 断开特定客户端
    bool disconnectClient(const std::string &client_id);

    // 停止服务器
    void stop();

    // 检查服务器是否运行中
    bool isRunning() const { return server_fd_ != -1 && running_; }

private:
    int server_fd_ = -1;
    std::atomic<bool> running_{false};
    std::map<std::string, int> client_fds_;
    std::mutex client_mutex_;
    std::thread accept_thread_;
    std::vector<std::thread> client_threads_;
    MessageCallback message_callback_ = nullptr;
    ClientConnectCallback client_connect_callback_ = nullptr;
    ClientDisconnectCallback client_disconnect_callback_ = nullptr;

    // 接受客户端连接的线程
    void acceptThread();

    // 处理单个客户端
    void handleClient(int client_fd, const std::string &client_id);

    // 生成客户端ID
    std::string generateClientId(const sockaddr_in &addr);
};